import type { ProColumns } from "@ant-design/pro-components";
import { ProTable } from "@ant-design/pro-components";
import API from "./services";
import { TYPE } from "../types";
import { useState } from "react";
import {
  Button, Modal, Radio, message, Skeleton, Descriptions, Alert,
} from "antd";
import type { DescriptionsItemType } from "antd/es/descriptions";
import { useAccess, Access } from "@umijs/max";

const statusMap: Record<number, string> = {
  200: "200 服务器成功返回请求的数据",
  400: "400 用户请求有错误，服务器忽略此次请求。",
  403: "403 用户没有权限",
  404: "404 服务器没有找到请求的数据",
  500: "500 服务器发生错误",
};
const typeMap: Record<number, "success" | "error" | "warning"> = {
  200: "success",
  400: "error",
  403: "warning",
  404: "warning",
  500: "error",
};
const dayMap: Record<number, string> = {
  0: "一小时", 1: "一天", 7: "一周", 30: "一月", 365: "一年",
};
const options: any[] = [];
for (const key in dayMap) {
  const value = dayMap[key];
  options.push({ value: parseInt(key), label: value });
}

export default () => {
  const [loading, loadingSet] = useState(false);
  const [day, daySet] = useState(0);
  const [visibleIP, visibleIPSet] = useState(false);
  const [ip, ipSet] = useState("");
  const [visibleUser, visibleUserSet] = useState(false);
  const [loadingUser, loadingUserSet] = useState(false);
  const [userId, userIdSet] = useState(0);
  const [userItems, userItemSet] = useState<DescriptionsItemType[]>([]);

  const ac = useAccess();

  const columns: ProColumns[] = [
    {
      title: "状态码",
      dataIndex: "status",
      width: 70,
      valueEnum: statusMap,
      renderText: (text: number) => (
        <Alert
          type={typeMap[text]}
          message={<label title={statusMap[text].split(" ")[1]}>{text}</label>}
        />
      ),
    },
    {
      title: "网络请求",
      dataIndex: "path",
      hideInSearch: true,
      ellipsis: true,
      renderText: (text: string, r: TYPE.LogItem) => (
        <>
          <div>{r.method + " " + text}</div>
          <div>{r.params}</div>
          {r.errMsg ? <div style={{ color: "red" }}>{r.errMsg}</div> : null}
        </>
      ),
    },
    { title: "访问路径", dataIndex: "path", hideInTable: true },
    {
      title: "访问者信息",
      dataIndex: "userId",
      hideInSearch: true,
      width: 220,
      renderText: (text: number, record: TYPE.LogItem) => (
        <>
          <div>
            <label>IP地址：</label>
            <Access accessible={ac.canUse("forbidIP")} fallback={record.ip}>
              <Button
                color="primary"
                variant="text"
                onClick={() => { ipSet(record.ip); visibleIPSet(true); }}
              >
                {record.ip}
              </Button>
            </Access>
          </div>
          {!text ? "" : (
            <div>
              <label>用户名：</label>
              <Access
                accessible={ac.canUse("forbidUser")}
                fallback={record.userName}
              >
                <Button
                  color="primary"
                  variant="text"
                  onClick={() => {
                    userIdSet(text);
                    visibleUserSet(true);
                    getUser(text);
                  }}
                >
                  {record.userName}
                </Button>
              </Access>
            </div>
          )}
        </>
      ),
    },
    { title: "客户端IP", dataIndex: "ip", hideInTable: true },
    { title: "用户ID", dataIndex: "userId", valueType: "digit", hideInTable: true },
    { title: "访问时间", dataIndex: "atTime", hideInSearch: true, width: 100 },
    { title: "访问时间", dataIndex: "atTime", hideInTable: true, valueType: "date" },
  ];

  const forbidIP = () => {
    loadingSet(true);
    API.forbidIP(ip, day).then((res: TYPE.Response) => {
      loadingSet(false);
      message.success(res.data);
      visibleIPSet(false);
    }).catch(() => loadingSet(false));
  };

  const forbidUser = () => {
    loadingSet(true);
    API.forbidUser(userId, day).then((res: TYPE.Response) => {
      loadingSet(false);
      message.success(res.data);
      visibleUserSet(false);
    }).catch(() => loadingSet(false));
  };

  const getUser = (id: number) => {
    loadingUserSet(true);
    API.getUser(id).then((res: TYPE.Response) => {
      loadingUserSet(false);
      const items: DescriptionsItemType[] = [];
      for (const key in res.data) {
        const value = res.data[key];
        // span=filled 表示独占一行
        items.push({ key, label: key, children: value, span: "filled" });
      }
      userItemSet(items);
    }).catch(() => {
      loadingUserSet(false);
      userItemSet([]); // 清空旧数据
    });
  };

  return (
    <>
      <ProTable
        headerTitle="访问日志"
        rowKey="id"
        columns={columns}
        request={API.logger}
        // pagination={{ pageSizeOptions: [30, 100, 1000], defaultPageSize: 30 }}
      />
      <Modal
        title={"封IP " + ip}
        open={visibleIP}
        confirmLoading={loading}
        onOk={forbidIP}
        onCancel={() => visibleIPSet(false)}
      >
        <Radio.Group
          value={day}
          onChange={e => daySet(e.target.value)}
          options={options}
        />
      </Modal>
      <Modal
        title="封用户"
        open={visibleUser}
        confirmLoading={loading}
        onOk={forbidUser}
        onCancel={() => visibleUserSet(false)}
        style={{ top: 0 }}
      >
        <Skeleton active loading={loadingUser}>
          {userItems.length ? (
            <Descriptions bordered title="用户信息" items={userItems} />
          ) : null}
        </Skeleton>
        <h3 style={{ marginTop: 24 }}>设置封禁时长：</h3>
        <Radio.Group
          value={day}
          onChange={e => daySet(e.target.value)}
          options={options}
        />
      </Modal>
    </>
  );
};
